package com.micro.ai.files.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.micro.ai.commons.exception.BusinessException;
import com.micro.ai.files.entity.FileAttachment;
import com.micro.ai.files.mapper.FileAttachmentMapper;
import com.micro.ai.files.service.FileAttachmentService;
import com.micro.ai.files.service.StorageService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.StringUtils;

import java.time.LocalDateTime;
import java.util.List;

/**
 * 文件附件服务实现
 * 
 * @author micro-ai
 * @since 0.0.1
 */
@Slf4j
@Service
public class FileAttachmentServiceImpl extends ServiceImpl<FileAttachmentMapper, FileAttachment> implements FileAttachmentService {

    @Autowired
    private StorageService storageService;

    @Override
    @Transactional(rollbackFor = Exception.class)
    public FileAttachment create(FileAttachment attachment) {
        if (attachment == null) {
            throw new BusinessException("F0000", "文件附件信息不能为空");
        }
        
        if (!StringUtils.hasText(attachment.getTenantId())) {
            throw new BusinessException("F0000", "租户ID不能为空");
        }
        
        if (!StringUtils.hasText(attachment.getFilename())) {
            throw new BusinessException("F0000", "文件名不能为空");
        }
        
        LocalDateTime now = LocalDateTime.now();
        attachment.setCreatedAt(now);
        
        boolean success = this.save(attachment);
        if (!success) {
            throw new BusinessException("F0003", "保存文件附件失败");
        }
        
        log.info("创建文件附件成功: fileId={}, filename={}, originalName={}", 
                attachment.getId(), attachment.getFilename(), attachment.getOriginalName());
        return attachment;
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public FileAttachment update(String id, FileAttachment attachment) {
        if (!StringUtils.hasText(id)) {
            throw new BusinessException("F0000", "文件ID不能为空");
        }
        if (attachment == null) {
            throw new BusinessException("F0000", "文件附件信息不能为空");
        }
        
        FileAttachment existing = this.getById(id);
        if (existing == null) {
            throw new BusinessException("F0002", "文件附件不存在: " + id);
        }
        
        attachment.setId(id);
        
        boolean success = this.updateById(attachment);
        if (!success) {
            throw new BusinessException("F0003", "更新文件附件失败");
        }
        
        log.info("更新文件附件成功: fileId={}", id);
        return attachment;
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void delete(String id) {
        if (!StringUtils.hasText(id)) {
            throw new BusinessException("F0000", "文件ID不能为空");
        }
        
        FileAttachment attachment = this.getById(id);
        if (attachment == null) {
            throw new BusinessException("F0002", "文件附件不存在: " + id);
        }
        
        // 删除物理文件
        if (StringUtils.hasText(attachment.getFilePath())) {
            try {
                // 使用文件路径作为对象名称删除
                String objectName = attachment.getFilePath();
                storageService.deleteFile(objectName);
                log.info("删除物理文件成功: objectName={}", objectName);
            } catch (Exception e) {
                log.warn("删除物理文件失败，继续删除数据库记录: fileId={}, error={}", id, e.getMessage());
            }
        }
        
        boolean success = this.removeById(id);
        if (!success) {
            throw new BusinessException("F0003", "删除文件附件失败");
        }
        
        log.info("删除文件附件成功: fileId={}, filename={}", id, attachment.getFilename());
    }

    @Override
    public Page<FileAttachment> pageQuery(int pageNum, int pageSize, String tenantId, 
                                          String keyword, String fileType, 
                                          String associatedType, String associatedId) {
        if (pageNum < 1) {
            pageNum = 1;
        }
        if (pageSize < 1 || pageSize > 100) {
            pageSize = 20;
        }
        
        Page<FileAttachment> page = new Page<>(pageNum, pageSize);
        LambdaQueryWrapper<FileAttachment> query = new LambdaQueryWrapper<>();
        
        if (StringUtils.hasText(tenantId)) {
            query.eq(FileAttachment::getTenantId, tenantId);
        }
        if (StringUtils.hasText(fileType)) {
            query.eq(FileAttachment::getFileType, fileType);
        }
        if (StringUtils.hasText(associatedType)) {
            query.eq(FileAttachment::getAssociatedType, associatedType);
        }
        if (StringUtils.hasText(associatedId)) {
            query.eq(FileAttachment::getAssociatedId, associatedId);
        }
        if (StringUtils.hasText(keyword)) {
            query.and(q -> q.like(FileAttachment::getFilename, keyword)
                          .or().like(FileAttachment::getOriginalName, keyword)
                          .or().like(FileAttachment::getDescription, keyword));
        }
        
        // 只查询未删除的文件
        query.isNull(FileAttachment::getDeletedAt);
        
        query.orderByDesc(FileAttachment::getCreatedAt);
        
        return this.page(page, query);
    }

    @Override
    public List<FileAttachment> listByAssociated(String tenantId, String associatedType, String associatedId) {
        LambdaQueryWrapper<FileAttachment> query = new LambdaQueryWrapper<>();
        
        if (StringUtils.hasText(tenantId)) {
            query.eq(FileAttachment::getTenantId, tenantId);
        }
        if (StringUtils.hasText(associatedType)) {
            query.eq(FileAttachment::getAssociatedType, associatedType);
        }
        if (StringUtils.hasText(associatedId)) {
            query.eq(FileAttachment::getAssociatedId, associatedId);
        }
        
        // 只查询未删除的文件
        query.isNull(FileAttachment::getDeletedAt);
        
        query.orderByDesc(FileAttachment::getCreatedAt);
        
        return this.list(query);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void deleteByAssociated(String tenantId, String associatedType, String associatedId) {
        List<FileAttachment> attachments = listByAssociated(tenantId, associatedType, associatedId);
        
        for (FileAttachment attachment : attachments) {
            // 删除物理文件
            if (StringUtils.hasText(attachment.getFilePath())) {
                try {
                    storageService.deleteFile(attachment.getFilePath());
                } catch (Exception e) {
                    log.warn("删除物理文件失败: fileId={}, error={}", attachment.getId(), e.getMessage());
                }
            }
            this.removeById(attachment.getId());
        }
        
        log.info("批量删除关联文件成功: tenantId={}, associatedType={}, associatedId={}, count={}", 
                tenantId, associatedType, associatedId, attachments.size());
    }
}

